import 'dart:convert';
import 'package:crypto/crypto.dart';
import 'dart:math';
import "dart:io";
import "package:dio/dio.dart";
import 'package:http_parser/http_parser.dart';

String ossAccessKeyId = 'LTAI4fgjJgBBwElR';

String ossAccessKeySecret = '6dTEWASAvopvKHP9czh2DGRs11FSNz';
// oss设置的bucket的名字
String bucket = 'cgq-blog';
// 发送请求的url,
String url = 'https://cgq-blog.oss-cn-guangzhou.aliyuncs.com/';

//prod
// const String ossAccessKeyId = 'LTAI4fgjJgBBwElR';

// const String ossAccessKeySecret = '6dTEWASAvopvKHP9czh2DGRs11FSNz';
// // oss设置的bucket的名字
// const String bucket = 'music-live';
// // 发送请求的url,
// const String url = 'http://music-live.oss-cn-hangzhou.aliyuncs.com/';

// 过期时间
const String expiration = '2075-01-01T12:00:00.000Z';

class OssUtil {
  //验证文本域
  static String _policyText =
      '{"expiration": "$expiration","conditions": [["content-length-range", 0, 1048576000]]}'; //UTC时间+8=北京时间

  //进行utf8编码
  // ignore: non_constant_identifier_names
  static List<int> _policyText_utf8 = utf8.encode(_policyText);
  //进行base64编码
  static String policy = base64.encode(_policyText_utf8);

  //再次进行utf8编码
  // ignore: non_constant_identifier_names
  static List<int> _policy_utf8 = utf8.encode(policy);

  // 工厂模式
  factory OssUtil() => _getInstance();

  static OssUtil get instance => _getInstance();
  static OssUtil _instance;

  OssUtil._internal();

  static OssUtil _getInstance() {
    // bool inProduction = bool.fromEnvironment("dart.vm.product");
    // if (inProduction) {
      ossAccessKeyId = 'LTAI4fgjJgBBwElR';
      ossAccessKeySecret = '6dTEWASAvopvKHP9czh2DGRs11FSNz';
      bucket = 'music-live';
      url = 'https://music-live.oss-cn-hangzhou.aliyuncs.com/';
    // }
    if (_instance == null) {
      _instance = new OssUtil._internal();
    }
    return _instance;
  }

  /*
  *获取signature签名参数
  */
  String getSignature(String _accessKeySecret) {
    //进行utf8 编码
    // ignore: non_constant_identifier_names
    List<int> AccessKeySecretUtf8 = utf8.encode(_accessKeySecret);
    //通过hmac,使用sha1进行加密
    List<int> signaturePre =
        new Hmac(sha1, AccessKeySecretUtf8).convert(_policy_utf8).bytes;
    //最后一步，将上述所得进行base64 编码
    String signature = base64.encode(signaturePre);
    return signature;
  }

  // ignore: slash_for_doc_comments
  /**
   * 生成上传上传图片的名称 ,获得的格式:photo/20171027175940_oCiobK
   * 可以定义上传的路径uploadPath(Oss中保存文件夹的名称)
   * @param uploadPath 上传的路径 如：/photo
   * @return photo/
   */
  String getImageUploadName(String uploadPath, String filePath) {
    String imageMame = "";
    var timestamp = new DateTime.now().millisecondsSinceEpoch;
    imageMame = timestamp.toString() + "_" + getRandom(6);
    if (uploadPath != null && uploadPath.isNotEmpty) {
      imageMame = uploadPath + "/" + imageMame;
    }
    var imageType =
        filePath?.substring(filePath.lastIndexOf("."), filePath.length);
    return '$imageMame$imageType';
  }

  String getImageName(String filePath) {
    String imageMame = "";
    var timestamp = new DateTime.now().millisecondsSinceEpoch;
    imageMame = 'app' + timestamp.toString() + "_" + getRandom(6);
    var imageType =
        filePath?.substring(filePath.lastIndexOf("."), filePath.length);
    return '$imageMame$imageType';
  }

  /*
  * 生成固定长度的随机字符串
  * */
  String getRandom(int num) {
    String alphabet = 'qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM';
    String left = '';
    for (var i = 0; i < num; i++) {
//    right = right + (min + (Random().nextInt(max - min))).toString();
      left = left + alphabet[Random().nextInt(alphabet.length)];
    }
    return left;
  }

  /*
  * 根据图片本地路径获取图片名称
  * */
  String getImageNameByPath(String filePath) {
    // ignore: null_aware_before_operator
    return filePath?.substring(filePath.lastIndexOf("/") + 1, filePath.length);
  }
}

class UploadOss {
  // 过期时间
  static String expiration = "2050-01-01T12:00:00.000Z";

  /*
   * @params file 要上传的文件对象
   * @params rootDir 阿里云oss设置的根目录文件夹名字
   * @param fileType 文件类型例如jpg,mp4等
   * @param callback 回调函数我这里用于传cancelToken，方便后期关闭请求
   * @param onSendProgress 上传的进度事件
   */

  static Future<String> upload(File file,
      {String rootDir = "moment",
      String fileType,
      dynamic onSendProgress}) async {
    // 生成oss的路径和文件名我这里目前设置的是moment/20201229/test.mp4
    String pathName =
        "$rootDir/${getDate()}/app-${getRandom(12)}.${fileType == null ? getFileType(file.path) : fileType}";
      
    // 请求参数的form对象
    FormData formdata = new FormData.fromMap({
      //文件名，随意
      'Filename': OssUtil.instance.getImageName(file.path),
      //"可以填写文件夹名（对应于oss服务中的文件夹）/" + fileName
      'key': pathName, //上传后的文件名
      'policy': OssUtil.policy,
      //Bucket 拥有者的AccessKeyId。
      'OSSAccessKeyId': ossAccessKeyId,
      //让服务端返回200，不然，默认会返回204
      'success_action_status': '200',
      'signature': OssUtil.instance.getSignature(ossAccessKeySecret),
      'file':getFileType(file.path)=='mp4'? MultipartFile.fromFileSync(file.path,filename:pathName,contentType: MediaType('video',getFileType(file.path)) ): MultipartFile.fromFileSync(file.path,filename:pathName)
      //必须放在参数最后
    });

    Dio dio = Dio();
    //  dio.options.responseType = ResponseType.plain;
    // dio.options.contentType = "multipart/form-data";
       dio.options.headers["content-type"] = "multipart/form-data";
    try {
      // 发送请求
      await dio.post(url, data: formdata,  options:Options(
        responseType: ResponseType.plain,
      contentType: "multipart/form-data",
    ),
          onSendProgress: (int progress, int total) {
        if (onSendProgress != null) {
          double percentage =
              double.parse(((progress / total) * 100).toStringAsFixed(2));

          onSendProgress(percentage);
          print("当前进度是 $progress 总进度是 $total   $percentage");
        }
      });
      print("${url}/$pathName");
      // 成功后返回文件访问路径
      return "${url}/$pathName";
    } catch (e) {
      print(e);
      return '';
    }
  }

  /*
  * 生成固定长度的随机字符串
  * */
  static String getRandom(int num) {
    String alphabet = "qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM";
    String left = "";
    for (var i = 0; i < num; i++) {
//    right = right + (min + (Random().nextInt(max - min))).toString();
      left = left + alphabet[Random().nextInt(alphabet.length)];
    }
    return left;
  }

  /*
  * 根据图片本地路径获取图片名称
  * */
  static String getImageNameByPath(String filePath) {
    // ignore: null_aware_before_operator
    return filePath?.substring(filePath.lastIndexOf("/") + 1, filePath.length);
  }

  /**
   * 获取文件类型
   */
  static String getFileType(String path) {
    print(path);
    List<String> array = path.split(".");
    return array[array.length - 1];
  }

  /// 获取日期
  static String getDate() {
    DateTime now = DateTime.now();
    return "${now.year}${now.month}${now.day}";
  }

  // 获取plice的base64
  static getSplicyBase64(String policyText) {
    //进行utf8编码
    List<int> policyText_utf8 = utf8.encode(policyText);
    //进行base64编码
    String policy_base64 = base64.encode(policyText_utf8);
    return policy_base64;
  }

  /// 获取签名
  static String getSignature(String policyText) {
    //进行utf8编码
    List<int> policyText_utf8 = utf8.encode(policyText);
    //进行base64编码
    String policy_base64 = base64.encode(policyText_utf8);
    //再次进行utf8编码
    List<int> policy = utf8.encode(policy_base64);
    //进行utf8 编码
    List<int> key = utf8.encode(ossAccessKeySecret);
    //通过hmac,使用sha1进行加密
    List<int> signature_pre = Hmac(sha1, key).convert(policy).bytes;
    //最后一步，将上述所得进行base64 编码
    String signature = base64.encode(signature_pre);
    return signature;
  }
}
